<template>
  <!-- Ready状态下 显示模态页面 -->
  <PageModal
    :prevent-back="preventBack"
    :back-text="backText"
    :show="showAdjustPage"
    :page-style="pageStyle"
    :footer-size="footerSize"
    :footer-style="footerStyle"
    @back="onBack"
    @close="closeModal"
  >
    <AdjustParameterView
      v-if="initialized && showControlView"
      ref="adjustParameterRef"
      :control="control"
      :program-name="customProgramNameGetter?.(activeProgramKey, activeProgramName, true) || activeProgramName"
      :program-remaining="activeProgramTips || activeProgramRemaining"
      :picker-keys="pickerKeys"
      :custom-params="customParams"
      :no-prefix="!$slots.prefix || noPrefix"
      :no-suffix="!$slots.suffix || noSuffix"
    >
      <template #prefix>
        <slot name="prefix"></slot>
      </template>
      <template #suffix>
        <slot name="suffix"></slot>
      </template>
      <template #desc>
        <view class="program-desc">{{ desc }}</view>
      </template>
    </AdjustParameterView>

    <template #footer>
      <view v-if="customFooter" class="custom-footer">
        <slot name="footer"></slot>
      </view>
      <view v-else class="start-footer">
        <slot name="start-footer"></slot>
        <ActionButton vibrate :disabled="isOffline === true" :plain-disabled="startDisabled" @click="startProgramNow">
          <view>{{ $t('Appliance.AdjustParameter.StartProgram.Button.Text') }}</view>
        </ActionButton>
      </view>
    </template>
  </PageModal>

  <!-- 运行状态下 显示抽屉组件 -->
  <Drawer
    type="confirm"
    no-cancel
    :height="drawerHeight"
    :show="showAdjustDrawer"
    :title="$t('Appliance.OrderProgram.AdjustOption.Title.Text')"
    :confirm-text="$t('APP.Common.Close.Text')"
    @close="closeModal"
  >
    <template #desc>
      <view class="selected-options">
        <text v-for="(optionName, index) in drawerOptionNames" :key="index">{{ optionName }}</text>
      </view>
    </template>

    <AdjustParameterView
      v-if="initialized && !showControlView"
      ref="adjustParameterRef"
      show-grid-only
      :control="control"
      :program-name="customProgramNameGetter?.(activeProgramKey, activeProgramName, true) || activeProgramName"
      :program-remaining="activeProgramTips || activeProgramRemaining"
      :picker-keys="pickerKeys"
      :custom-params="customParams"
      :no-prefix="!$slots.prefix || noPrefix"
      :no-suffix="!$slots.suffix || noSuffix"
    >
      <template #prefix>
        <slot name="prefix"></slot>
      </template>
      <template #suffix>
        <slot name="suffix"></slot>
      </template>
    </AdjustParameterView>
  </Drawer>
</template>

<script setup lang="ts">
import type { CSSProperties } from 'vue'
import ActionButton from '@/common/actionButton/actionButton.vue'
import { footerStyle, footerSize } from '@/layout/appliance/style'
import AdjustParameterView from './adjustParameterView.vue'
import type { BaseController } from '@/controller/BaseAppliance/definition'
import { useControlState } from '@/controller/BaseAppliance/useControl'
import type { ApplianceProgram, ProgramSelectOption } from '@/api/appliance'
import type { CustomOption } from '../components/parameterCard.vue'
import PageModal from '@/common/pageModal.vue'
import { OptionBatchObserve } from '@/controller/common/Program/program'
import { checkStartProgramAccessable, checkValleyTimeAccessable } from '@/controller/common/ErrorHandler/validator'
import { orderPermanentInfo } from '@/utils/deviceMessageSubscribe/deviceMessage'
import type { CustomProgramNameGetter } from '../components/programList.vue'
import Drawer from '@/common/drawer.vue'
import { TrackType, trackEvent } from '@/dataReport/tracks'
import { safeTrack } from '@/dataReport/dataReportUtil'
import { OPERATION_STATES } from '@/constants/Command'
import { useEnvStore } from '@/store/env'

const props = defineProps<{
  show: boolean
  control: BaseController.Control
  manualLoadParameter?: boolean
  backText?: string // 返回文本
  preventBack?: boolean // 是否阻止默认返回关闭弹框
  customFooter?: boolean // 是否自定义Footer (使用Footer插槽)
  noPrefix?: boolean
  noSuffix?: boolean
  /**
   * 调节参数Key 配置
   */
  pickerKeys?: string[] // 需要展示为Picker组件的 Key
  customParams?: CustomOption[] // 自定义处理逻辑的 Key (在Checkbox类型的卡片中显示)
  activeProgramTips?: string // 当前程序显示的程序提示文本
  customProgramNameGetter?: CustomProgramNameGetter // 自定义程序名称
}>()
const emit = defineEmits<{
  (e: 'update:show', show: boolean): void
  (e: 'back', parameterOptions: ProgramSelectOption[]): void
  (e: 'close'): void
}>()

defineExpose<{
  getParameterOptions: () => ProgramSelectOption[]
  getActivedParameterNames: () => string[]
}>({
  getParameterOptions,
  getActivedParameterNames,
})

const envStore = useEnvStore()
const { isOffline, showControlView, startDisabled } = useControlState(props.control)

/**
 * 页面
 */
const initialized = ref(false)
const pageStyle: CSSProperties = {
  backgroundColor: '#ffffff',
}
function closeModal() {
  emit('update:show', false)
  emit('close')
}

/**
 * 显示状态判断
 */
const showAdjustPage = computed(() => props.show && showControlView.value)
const showAdjustDrawer = computed(() => props.show && !showControlView.value)
// 显示状态切换时 自动关闭调节参数 防止Modal/Drawer闪烁且数据不对的问题
watch(
  () => showControlView.value,
  () => props.show && closeModal()
)
watchEffect(() => {
  // 当显示抽屉 且 状态不可调节时 自动关闭抽屉
  if (showAdjustDrawer.value && !props.control.store.isAdjustableOperationState) {
    closeModal()
  }
})
const drawerHeight = computed(() => `${envStore.systemInfo.screenHeight - envStore.titleBarHeight}px`)

function onBack() {
  const parameterOptions = getParameterOptions()

  emit('back', parameterOptions)

  if (props.preventBack) return

  emit('close')
}

/**
 * 当前程序
 */
const activeProgram = computed(() => props.control.store.currentProgram)
const activeProgramKey = computed(() => props.control.store.currentProgramKey)
const activeProgramName = computed(() => props.control.store.currentProgramName)
const activeProgramRemaining = computed(() => props.control.store.programRemainingText)
const desc = computed(
  () => props.control.store.availableParameter?.mediumDescription || activeProgram.value?.mediumDescription
)

/**
 * 调节参数
 */
const adjustParameterRef = ref<InstanceType<typeof AdjustParameterView> | null>(null)
// 抽屉显示已选中参数描述
const drawerOptionNames = computed(() => {
  const selectionOptionNames: string[] = []
  const checkedOptionNames: string[] = []

  for (const activedOption of props.control.store.activedOptionNames) {
    // 过滤可调节的配置
    const isAdjustableOption = props.control.store.adjustableOptions.some(
      (adjustOption) => adjustOption.key === activedOption.key
    )
    if (isAdjustableOption) continue

    if (activedOption.value !== void 0) {
      selectionOptionNames.push(`${activedOption.label} ${activedOption.value}`)
    } else {
      checkedOptionNames.push(activedOption.label)
    }
  }

  return selectionOptionNames.concat(checkedOptionNames)
})

watch(
  () => props.show,
  (show) => {
    // 首次打开弹框初始化
    if (show) {
      initialized.value = true
    }

    // 虚拟家电 直接加载
    if (props.control.store.isVirtualAppliance) {
      show && props.control.store.loadAvailableParameter()
      return
    }

    // 添加/移除Option监听触发事件
    show
      ? props.control.remote.addBatchObserve(OptionBatchObserve)
      : props.control.remote.removeBatchObserve(OptionBatchObserve)

    // 打开弹框 非手动加载接口
    if (show && !props.manualLoadParameter) {
      props.control.store.loadAvailableParameter()
    }
  },
  {
    immediate: true,
  }
)

function getParameterOptions() {
  return adjustParameterRef.value?.getParameterOptions?.() || []
}
function getActivedParameterNames() {
  return adjustParameterRef.value?.getActivedParameterNames?.() || []
}

/**
 * 立即启动
 */
async function startProgramNow() {
  safeTrack(() => {
    trackEvent('Appliance.AdjustParameter.StartProgram.Button.Text', {}, TrackType.ApplianceDetail)
  })
  // 调接口前检查
  if (!checkStartProgramAccessable(props.control)) return
  // 谷电时间检查
  const valleyTimeAccessable = await checkValleyTimeAccessable(props.control, {
    onAccessable: async () => {
      // 永久消息订阅
      try {
        await orderPermanentInfo(props.control.store._datasource.haId)
      } catch (e) {
        console.error(e)
      }
    },
  })
  if (!valleyTimeAccessable) return

  const parameterOptions = getParameterOptions()
  const currentProgram = activeProgram.value as ApplianceProgram.Scope
  await props.control.store.startProgramNow(
    currentProgram,
    parameterOptions,
    'Appliance.AdjustParameter.StartProgram.Button.Text'
  )
  closeModal()
}
</script>

<style scoped lang="less">
.program-desc {
  font-weight: 400;
  font-size: 28rpx;
  line-height: 40rpx;
  color: #818790;
}
.selected-options {
  color: var(--dark-color);
  font-size: 36rpx;
  font-weight: 500;
  line-height: 50rpx;
  margin-bottom: 32rpx;
  > text {
    margin-right: 48rpx;
    margin-bottom: 32rpx;
  }
}
.start-footer {
  display: flex;
  align-items: center;
  action-button {
    flex: 1;
  }
}
</style>
